home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Online / SpeakFreely / src / vox.c < prev    next >
C/C++ Source or Header  |  2000-05-18  |  15KB  |  549 lines

  1. /* vox.c
  2.  
  3.    Dave Hawkes 27/IX/95
  4.  
  5.    This rle codes the GSM or other compression to reduce data
  6.    at low signal levels.  */
  7.  
  8. #include "speakfree.h"
  9.  
  10. extern gsm gsmh;              /* GSM handle */
  11.  
  12. #define FAR
  13.  
  14. #ifdef NEEDED
  15. static int rlecomp(int len, char FAR *lpData, char FAR *lpBuffer)
  16. {
  17.     char FAR *lpDCount;
  18.     char FAR *lpStart;
  19.     int i, scnt, dcnt;
  20.     scnt = 1;
  21.     dcnt = 0;
  22.     lpDCount = NULL;
  23.     lpStart = lpBuffer;
  24.     for(i = 1; i < len; ++i) {
  25.     ++lpData;
  26.     if(*lpData == *(lpData - 1)) {
  27.         if(scnt > 0) {
  28.         ++scnt;
  29.         if(scnt >= 3) {
  30.             if(dcnt > 0) {
  31.             *lpDCount = dcnt - 1;
  32.             --lpBuffer;
  33.             dcnt = 0;
  34.             }
  35.             if(scnt >= 120) {
  36.             *lpBuffer++ = scnt | 0x80;
  37.             *lpBuffer++ = *lpData;
  38.             scnt = 0;
  39.             }
  40.         }
  41.         } else {
  42.         scnt = (dcnt > 0) ? 2 : 1;
  43.         }
  44.     } else {
  45.         if(dcnt > 0) {
  46.         if(scnt > 0) {
  47.             dcnt += scnt - 1;
  48.             while(--scnt)
  49.             *lpBuffer++ = *(lpData - 1);
  50.         }
  51.         ++dcnt;
  52.         if(dcnt >= 120) {
  53.             *lpDCount = dcnt;
  54.             scnt = 0;
  55.             dcnt = 0;
  56.         }
  57.         *lpBuffer++ = *lpData;
  58.         } else {
  59.         if(scnt >= 3) {
  60.             *lpBuffer++ = scnt | 0x80;
  61.             *lpBuffer++ = *(lpData - 1);
  62.             scnt = 1;
  63.             dcnt = 0;
  64.         } else if(scnt == 0) {
  65.             scnt = 1;
  66.         } else {
  67.             lpDCount = lpBuffer++;
  68.             dcnt = 1 + scnt;
  69.             while(scnt--) {
  70.             *lpBuffer++ = *(lpData - 1);
  71.             }
  72.             *lpBuffer++ = *lpData;
  73.         }
  74.         }
  75.     }
  76.     }
  77.     if(dcnt > 0) {
  78.     if(scnt > 0) {
  79.         dcnt += scnt - 1;
  80.         while(--scnt)
  81.         *lpBuffer++ = *(lpData - 1);
  82.     }
  83.     *lpDCount = dcnt;
  84.     } else if(scnt >= 3) {
  85.     *lpBuffer++ = scnt | 0x80;
  86.     *lpBuffer++ = *(lpData - 1);
  87.     } else if(scnt > 0) {
  88.     if(!lpDCount) {
  89.         lpDCount = lpBuffer++;
  90.         *lpDCount = 0;
  91.     }
  92.     *lpDCount += scnt;
  93.     while(scnt--)
  94.         *lpBuffer++ = *(lpData - 1);
  95.     }
  96.     return lpBuffer - lpStart;
  97. }
  98. #endif
  99.  
  100. static int rledecomp(len, lpData, lpBuffer)
  101.   int len;
  102.   char *lpData, *lpBuffer;
  103. {
  104.     int j, cnt, val;
  105.     char FAR *lpStart;
  106.     char FAR *lpEnd;
  107.     if(*lpBuffer == (char) ((unsigned char) 0x80)) {
  108.     bzero(lpData, len);
  109.     return len;
  110.     }
  111.     lpStart = lpData;
  112.     lpEnd = lpData + len;
  113.     while(lpData < lpEnd) {
  114.     if(*lpBuffer & 0x80) {
  115.         cnt = *lpBuffer++ & 0x7f;
  116.         val = *lpBuffer++;
  117.         for(j = 0; j < cnt; ++j)
  118.         *lpData++ = val;
  119.     } else {
  120.         cnt = *lpBuffer++;
  121.         for(j = 0; j < cnt; ++j)
  122.         *lpData++ = *lpBuffer++;
  123.     }
  124.     }
  125.     return lpData - lpStart;
  126. }
  127.  
  128. static gsm_frame gsm_zero = {
  129.     216, 32, 162, 225, 90, 80, 0, 73, 36, 146, 73, 36, 80, 0, 73, 36, 146, 73,
  130.     36, 80, 0, 73, 36, 146, 73, 36, 80, 0, 73, 36, 146, 73, 36 };
  131.  
  132. static char buffer[BUFL];
  133.  
  134. #ifdef NEEDED
  135.  
  136. #define GAIN_LEVELS    64
  137. #define GAIN_HANG        10
  138.  
  139. static int av_var = 2;
  140. static int av_samples = 250;
  141.  
  142. static long packet_size = 0;
  143. static int frame_size = 160;
  144.  
  145. static long gain_threshold = 0;
  146. static int kill_count = 0;
  147. static int vox_speed = 0;
  148. int noise_threshold = 32;
  149. static int gain_max = GAIN_LEVELS + GAIN_HANG;
  150. static int gain_kill = 25;
  151. static int decay_mask = 160;
  152. static int attack_mask = 4;
  153. int VoxForceReset = 0;
  154.  
  155. static int gain = GAIN_LEVELS + GAIN_HANG;
  156.  
  157. void vox_gsmcomp(struct soundbuf *asb, int use_GSM)
  158. {
  159.     gsm_signal src[244];    /* max frame size from load_vox_type_params */
  160.     gsm_frame dst;
  161.     int i, j, sz, l;
  162.     char *dp = (asb->buffer.buffer_val) + sizeof(short);
  163.     LONG ldata = asb->buffer.buffer_len; 
  164.     int nframes;
  165.     int sv, mx, mn, allzero;
  166.     static long mx_diff;
  167.     static int mx_av, mn_av, av_cnt = 0;
  168.     static int decay_rem = 0, attack_rem = 0;
  169.     long diff, av, local_mx_diff;
  170.     static int NotDetectNoise = 0;
  171.     static int DetectNoise = 0;
  172.     
  173.     if(packet_size != ldata) {
  174.     if(!load_vox_type_params(0))
  175.         return; /* We don't support this size */
  176.     }
  177.     
  178.     nframes = (int) ((ldata + frame_size - 1) / frame_size);
  179.  
  180.     l = nframes * sizeof(dst);
  181.     allzero = 1;
  182.     local_mx_diff = 0;
  183.     for (i = 0; i < ldata; i += frame_size) {
  184.     mx = mn = audio_u2s(asb->buffer.buffer_val[0]);
  185.     av = 0;
  186.     for (j = 0; j < frame_size; j++) {
  187.         if ((i + j) < ldata) {
  188.         sv = audio_u2s(asb->buffer.buffer_val[i + j]);
  189.         if(sv > mx)
  190.             mx = sv;
  191.         else if(sv < mn)
  192.             mn = sv;
  193.         src[j] = sv;
  194.         av += abs(sv);
  195.         } else {
  196.         sv = audio_u2s(asb->buffer.buffer_val[i + j - frame_size]);
  197.         if(sv > mx)
  198.             mx = sv;
  199.         else if(sv < mn)
  200.             mn = sv;
  201.         av += abs(sv);
  202.         src[j] = 0;
  203.         }
  204.     }
  205.     diff = (long) mx - mn;
  206.     if(diff > local_mx_diff)
  207.       local_mx_diff = diff;
  208.     av /= frame_size;
  209. #ifdef ALLOW_VOX_WAVE
  210.     if(1)
  211. #else
  212.     if(!isWaveSound) {  /* stop wave sounds upsetting VOX levels */
  213. #endif
  214.         if(av_cnt++ == 0) {
  215.         mx_av = mn_av = (int) av;
  216.         mx_diff = diff;
  217.         } else {
  218.         if(av_var * mn_av >= mx_av) {
  219.             if((int) av > mx_av)
  220.             mx_av = (int) av;
  221.             if((int) av < mn_av)
  222.             mn_av = (int) av;
  223.             if(diff > mx_diff)
  224.             mx_diff = diff;
  225.             if(av_cnt >= av_samples) {
  226.             av_cnt = 0;
  227.             if(VoxForceReset || (gain_threshold == 0)) {
  228.                 gain_threshold = mx_diff;
  229.                 VoxForceReset = 0;
  230.             } else
  231.                 gain_threshold = ((15 * gain_threshold + mx_diff) / 16);
  232.             NotDetectNoise = 0;
  233.             if(++DetectNoise > 20) {
  234.                 if(--av_var < 2)
  235.                   av_var = 2;
  236.                 DetectNoise = 0;
  237.             }
  238.             }
  239.         } else {
  240.             av_cnt = 0;
  241.             if(++NotDetectNoise > 3000) {
  242.             NotDetectNoise = 2500;
  243.             ++av_var;
  244.             }
  245.             DetectNoise = 0;
  246.         }
  247.         }
  248.         if((16 * diff) < (noise_threshold * gain_threshold)) {
  249.         if(gain <= GAIN_LEVELS) {
  250.             attack_rem = 0;
  251.             if(gain > 0) {
  252.             allzero = 0;
  253.             for (j = 0; j < frame_size; j++) {
  254.                 if(((j + decay_rem) % decay_mask) == 0)
  255.                 if(gain > 0)
  256.                     --gain;
  257.                 src[j] = (int) ((src[j] * (long) gain) / GAIN_LEVELS);
  258.             }
  259.             decay_rem = (decay_rem + frame_size) % decay_mask;
  260.             } else {
  261.             bzero(src, frame_size * sizeof(src[0]));
  262.             decay_rem = 0;
  263.             }
  264.             if(!use_GSM) {
  265.             for (j = 0; j < frame_size; j++) {
  266.                 asb->buffer.buffer_val[i + j] = audio_s2u(src[j]);
  267.             }
  268.             }
  269.         } else {
  270.             attack_rem = decay_rem = 0;
  271.             allzero = 0;
  272.             --gain;
  273.         }
  274.         } else if(gain < GAIN_LEVELS) {
  275.         decay_rem = 0;
  276.         allzero = 0;
  277.         for (j = 0; j < frame_size; j++) {
  278.             if(((j + attack_rem) % attack_mask) == 0)
  279.             if(++gain >= GAIN_LEVELS) {
  280.                 gain = gain_max;
  281.                 attack_rem = 0;
  282.                 break;
  283.             }
  284.             src[j] = (int) ((src[j] * (long) gain) / GAIN_LEVELS);
  285.         }
  286.         attack_rem = (attack_rem + frame_size) % attack_mask;
  287.         if(!use_GSM) {
  288.             for (j = 0; j < frame_size; j++) {
  289.             asb->buffer.buffer_val[i + j] = audio_s2u(src[j]);
  290.             }
  291.         }
  292.         }
  293.     } else {
  294.         decay_rem = 0;
  295.         attack_rem = 0;
  296.         allzero = 0;
  297.         gain = gain_max;
  298.         kill_count = 0;
  299.     }
  300.     
  301.     if(use_GSM) {
  302.         gsm_encode(gsmh, src, dst);
  303.         for(j = 0; j < sizeof(dst); ++j) {
  304.         dp[j] = dst[j] - gsm_zero[j];
  305.         }
  306.         dp += sizeof dst;
  307.     }
  308.     }
  309.     
  310.     voxMonitorUpdate(local_mx_diff, (noise_threshold * gain_threshold) / 16);
  311.     if(!use_GSM) {
  312.     if(allzero) {
  313.         if(++kill_count > gain_kill) {
  314.         asb->buffer.buffer_len = 0;
  315.         kill_count = gain_kill;
  316.         }
  317.     } else
  318.         kill_count = 0;
  319.     return;
  320.     }
  321.  
  322.     sz = rlecomp(l, (char *) (asb->buffer.buffer_val) + sizeof(short), buffer);
  323.  
  324.     /* Hide original uncompressed buffer length in first 2 bytes of buffer. */
  325.     
  326.     if(sz >= l) {
  327.     asb->buffer.buffer_len = l + sizeof(short);
  328.     *((short *) asb->buffer.buffer_val) = (short) ldata;
  329.     kill_count = 0;
  330.     } else {
  331.     if(allzero) {
  332.         if(++kill_count > gain_kill) {
  333.         ldata |= 0x4000;
  334.         kill_count = gain_kill;
  335.         }
  336.         sz = 1;
  337.         *((char *) (asb->buffer.buffer_val) + sizeof(short)) = (char) ((unsigned char) 0x80);
  338.     } else {
  339.         memcpy((char *) (asb->buffer.buffer_val) + sizeof(short), buffer, sz);
  340.         kill_count = 0;
  341.     }
  342.     asb->buffer.buffer_len = sz + sizeof(short);
  343.     *((short *) asb->buffer.buffer_val) = (short) ldata | 0x8000;
  344.     }
  345.     *((short *)  asb->buffer.buffer_val) = htonl(*(short *) asb->buffer.buffer_val);
  346. }
  347. #endif
  348.  
  349. void vox_gsmdecomp(sb)
  350.   struct soundbuf *sb;
  351. {
  352.     gsm_signal dst[160];
  353.     int i, j, isz, l = 0;
  354.     static char dcb[BUFL];
  355.     short declen = ntohl(*((short *) sb->buffer.buffer_val));
  356.     int cmpr;
  357.     char *pbuffer;
  358.     
  359.     cmpr = (declen & 0x8000);
  360.     declen &= ~(0x8000 | 0x4000);
  361.     if (declen <= 0 || declen > 1600) {
  362.     declen = 1600;
  363.     }
  364.     if(cmpr) {
  365.     rledecomp(declen, buffer, ((char *) sb->buffer.buffer_val) + sizeof(short));
  366.     pbuffer = buffer;
  367.     } else
  368.     pbuffer = ((char *) sb->buffer.buffer_val) + sizeof(short);
  369.     for (i = 0; i < sb->buffer.buffer_len - sizeof(short);
  370.         i += sizeof(gsm_frame)) {
  371.     isz = 0;
  372.     for(j = 0; j < sizeof(gsm_frame); ++j) {
  373.         isz |= pbuffer[j];
  374.         pbuffer[j] += gsm_zero[j];
  375.     }
  376.     if(isz == 0) {
  377.         memset(dcb, audio_s2u(0), sizeof(dcb));
  378.         l += 160;
  379.     } else {
  380.         gsm_decode(gsmh, (gsm_byte *) pbuffer, dst);
  381.         for (j = 0; j < 160; j++) {
  382.         dcb[l++] = audio_s2u(dst[j]);
  383.         }
  384.     }
  385.     pbuffer += sizeof(gsm_frame);
  386.     }
  387.     bcopy(dcb, sb->buffer.buffer_val, declen);
  388.     sb->buffer.buffer_len = declen;
  389. }
  390.  
  391. #ifdef NEEDED
  392. int load_vox_type_params(int Force)
  393. {
  394.     static int OldVoxMode = IDM_VOX_NONE;
  395.     const int speed_ids[] = { IDS_PF_VOX_SLOW, IDS_PF_VOX_MEDIUM, IDS_PF_VOX_FAST };
  396.     int i;
  397.     char buf[16];
  398.     char *pfn = rstring(IDS_PF_PROFILE_FILE);
  399.     int sample_count = inputSampleCount();
  400.     
  401.     if(!Force && (sample_count == packet_size))
  402.     return 1;
  403.     
  404.     switch(sample_count) {
  405.     case 3200:
  406.     case 1600:
  407.         packet_size = sample_count;
  408.         frame_size = 160;
  409.         break;
  410.     case 3600:
  411.     case 1800:
  412.         packet_size = sample_count;
  413.         frame_size = 180;
  414.         break;
  415.     case 1948:
  416.         packet_size = sample_count;
  417.         frame_size = 150;    /* 2 bytes over - but should be OK */
  418.         break;
  419.     case 972:
  420.         packet_size = sample_count;
  421.         frame_size = 162;
  422.         break;
  423.     case 976:
  424.     case 488:
  425.         packet_size = sample_count;
  426.         frame_size = 244;
  427.         break;
  428.     default:
  429.         return 0;
  430.     }
  431.  
  432.     switch(voxmode) {
  433.     case IDM_VOX_FAST: vox_speed = 2; break;
  434.     case IDM_VOX_MEDIUM: vox_speed = 1; break;
  435.     case IDM_VOX_SLOW: vox_speed = 0; break;
  436.     case IDM_VOX_NONE: vox_speed = 0; break;
  437.     default: vox_speed = 0; voxmode = IDM_VOX_NONE; break;
  438.     }
  439.     
  440.     if(OldVoxMode != IDM_VOX_NONE) {
  441.     switch(OldVoxMode) {
  442.         case IDM_VOX_FAST: i = 2; break;
  443.         case IDM_VOX_MEDIUM: i = 1; break;
  444.         case IDM_VOX_SLOW: i = 0; break;
  445.         default: i = 0; break;
  446.     }
  447.     _itoa(noise_threshold, buf, 10);
  448.     WritePrivateProfileString(rstring(speed_ids[i]), rstring(IDS_PF_VOX_NOISE_THRESH), buf, pfn);
  449.     }
  450.     OldVoxMode = voxmode;
  451.     
  452.     av_samples = (int) (((long) 5000 * 8 + frame_size / 2) / frame_size);   /* 5 seconds */
  453.     noise_threshold = GetPrivateProfileInt(rstring(speed_ids[vox_speed]), rstring(IDS_PF_VOX_NOISE_THRESH), noise_threshold, pfn);
  454.     pfn = rstring(IDS_PF_PROFILE_FILE); /* refresh */
  455.     i = (int) (((long) attack_mask * GAIN_LEVELS + 4) / 8);
  456.     i = GetPrivateProfileInt(rstring(speed_ids[vox_speed]), rstring(IDS_PF_VOX_ATTACK), i, pfn);
  457.     attack_mask = (int) (((long) i * 8 + GAIN_LEVELS / 2) / GAIN_LEVELS);
  458.     if(attack_mask < 1)
  459.     attack_mask = 1;
  460.     i = (int) (((long) (gain_max - GAIN_LEVELS) * frame_size + 4) / 8);
  461.     i = GetPrivateProfileInt(rstring(speed_ids[vox_speed]), rstring(IDS_PF_VOX_HOLD), i, pfn);
  462.     gain = gain_max = (int) (((long) i * 8 + frame_size / 2) / frame_size) + GAIN_LEVELS;
  463.     pfn = rstring(IDS_PF_PROFILE_FILE); /* refresh */
  464.     i = (int) (((long) decay_mask * GAIN_LEVELS + 4) / 8);
  465.     i = GetPrivateProfileInt(rstring(speed_ids[vox_speed]), rstring(IDS_PF_VOX_DECAY), i, pfn);
  466.     decay_mask = (int) (((long) i * 8 + GAIN_LEVELS / 2) / GAIN_LEVELS);
  467.     if(decay_mask < 1)
  468.     decay_mask = 1;
  469.     i = (int) (((long) gain_kill * packet_size + 4) / 8);
  470.     i = GetPrivateProfileInt(rstring(speed_ids[vox_speed]), rstring(IDS_PF_VOX_RELEASE), i, pfn);
  471.     gain_kill = (int) (((long) i * 8 + packet_size / 2) / packet_size);
  472.     voxMonitorUpdate(0, (noise_threshold * gain_threshold) / 16);
  473.     return 1;
  474. }
  475.  
  476. /*  VOX_RESET_PARAMETERS  --  Reset all VOX parameters to defaults */
  477.  
  478. void vox_reset_parameters(void)
  479. {
  480.     gain_threshold = 0;
  481.     kill_count = 0;
  482.     vox_speed = 0;
  483.     noise_threshold = 32;
  484.     gain_max = GAIN_LEVELS + GAIN_HANG;
  485.     gain_kill = 25;
  486.     decay_mask = 160;
  487.     attack_mask = 4;
  488.     load_vox_type_params(1);    
  489. }
  490.  
  491. int load_vox_params(void)
  492. {
  493.     char *pfn = rstring(IDS_PF_PROFILE_FILE);
  494.     const int speed_ids[] = { IDS_PF_VOX_SLOW, IDS_PF_VOX_MEDIUM, IDS_PF_VOX_FAST };
  495.     int h[] = { 1000, 500, 250 };
  496.     int d[] = { 1000, 500, 250 };
  497.     int r[] = { 5000, 1000, 0 };
  498.     char buf[16];
  499.     int i, n;
  500.     
  501.     gain_threshold = GetPrivateProfileInt(rstring(IDS_PF_VOX), rstring(IDS_PF_VOX_GAIN), (int) gain_threshold, pfn);
  502.     voxmode = GetPrivateProfileInt(rstring(IDS_PF_VOX), rstring(IDS_PF_VOX_SPEED), voxmode, pfn);
  503.     breakinput = GetPrivateProfileInt(rstring(IDS_PF_VOX), rstring(IDS_PF_VOX_BREAK), 0, pfn);
  504.     for(i = 0; i < 3; ++i) {
  505.     pfn = rstring(IDS_PF_PROFILE_FILE); /* refresh */
  506.     n = GetPrivateProfileString(rstring(speed_ids[i]), rstring(IDS_PF_VOX_NOISE_THRESH), "", buf, sizeof(buf), pfn);
  507.     if(n == 0) {
  508.         _itoa(32, buf, 10);
  509.         WritePrivateProfileString(rstring(speed_ids[i]), rstring(IDS_PF_VOX_NOISE_THRESH), buf, pfn);
  510.         _itoa(32, buf, 10);
  511.         WritePrivateProfileString(rstring(speed_ids[i]), rstring(IDS_PF_VOX_ATTACK), buf, pfn);
  512.         pfn = rstring(IDS_PF_PROFILE_FILE); /* refresh */
  513.         _itoa(h[i], buf, 10);
  514.         WritePrivateProfileString(rstring(speed_ids[i]), rstring(IDS_PF_VOX_HOLD), buf, pfn);
  515.         _itoa(d[i], buf, 10);
  516.         WritePrivateProfileString(rstring(speed_ids[i]), rstring(IDS_PF_VOX_DECAY), buf, pfn);
  517.         _itoa(r[i], buf, 10);
  518.         WritePrivateProfileString(rstring(speed_ids[i]), rstring(IDS_PF_VOX_RELEASE), buf, pfn);
  519.     }
  520.     }
  521.     load_vox_type_params(1);
  522.     return 1;
  523. }
  524.  
  525. int save_vox_params(void)
  526. {
  527.     const int speed_ids[] = { IDS_PF_VOX_SLOW, IDS_PF_VOX_MEDIUM, IDS_PF_VOX_FAST };
  528.     char *pfn = rstring(IDS_PF_PROFILE_FILE);
  529.     char buf[16];
  530.     int i;
  531.     _ltoa(gain_threshold, buf, 10);
  532.     WritePrivateProfileString(rstring(IDS_PF_VOX), rstring(IDS_PF_VOX_GAIN), buf, pfn);
  533.     _ltoa(breakinput, buf, 10);
  534.     WritePrivateProfileString(rstring(IDS_PF_VOX), rstring(IDS_PF_VOX_BREAK), buf, pfn);
  535.     _ltoa(voxmode, buf, 10);
  536.     WritePrivateProfileString(rstring(IDS_PF_VOX), rstring(IDS_PF_VOX_SPEED), buf, pfn);
  537.     pfn = rstring(IDS_PF_PROFILE_FILE);
  538.     switch(voxmode) {
  539.     case IDM_VOX_FAST: i = 2; break;
  540.     case IDM_VOX_MEDIUM: i = 1; break;
  541.     case IDM_VOX_SLOW: i = 0; break;
  542.     default: i = 0; break;
  543.     }
  544.     _itoa(noise_threshold, buf, 10);
  545.     WritePrivateProfileString(rstring(speed_ids[i]), rstring(IDS_PF_VOX_NOISE_THRESH), buf, pfn);
  546.     return 1;
  547. }
  548. #endif
  549.